home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "sysup.h"
- #ifdef MSDOS
- #include <errno.h>
- #include <string.h>
- #include <stdlib.h>
-
- #include "modern.h"
- #include "define.h"
- #include "qic02.h"
-
- #define MAXLEX 8
- #define SKIP_RESET 0x80
-
- static int board_type = UNUSED;
- static struct init_data id = { UNUSED, UNUSED, UNUSED };
- static int no_rewind = FALSE;
- static BYTE cmdset = 0;
- static struct { int nqic; BYTE tracks, command; } qiclist[] = {
- { 11, 4, Q2_QIC11 }, { 24, 9, Q2_QIC24 },
- { 120, 15, Q2_QIC120 }, { 150, 18, Q2_QIC150 },
- { 300, -1, 0x2A }, { 2100,-1, 0x2A },
- { 600, -1, 0x2B }, { 2200,-1, 0x2B },
- };
-
- int qparse(char *s)
- {
- static char already[] = "tape fromat already defined";
- char lex[MAXLEX+1], *errmsg;
- register i, k;
-
- for (i=0; i<MAXLEX && *s && *s!='.'; i++) {
- if (*s == ':' || *s == ';' || *s == ',') goto test_name;
- lex[i] = *s++;
- }
- return FALSE;
- test_name:
- lex[i] = '\0';
- if ((board_type=streamer('?', lex, 0)) < 0) return FALSE;
-
- id.base_address = UNUSED;
- id.dma_number = UNUSED;
- id.irq_number = UNUSED;
- no_rewind = FALSE;
-
- while (*++s) {
- for (i=0; i<=MAXLEX; ++i, s++) {
- if (*s >= 'A' && *s <= 'Z') lex[i] = *s | ('z'^'Z');
- else if (*s >= 'a' && *s <= 'z') lex[i] = *s;
- else break;
- }
- if (i < 1 || i > MAXLEX) {
- errmsg = "device parameter error"; goto error;
- }
- lex[i] = '\0'; /* for diagnostic printing */
- if (!strncmp("norewind", lex, i)) {
- no_rewind = TRUE;
- } else if (!strncmp("qic", lex, i)) {
- if (cmdset) {
- errmsg = already; goto error;
- }
- if (*s == '-') {
- ++s;
- } else {
- if (*s == ':') ++s;
- if (*s == '=') ++s;
- }
- if (*s >= '1' && *s <= '9') {
- k = 0; i = 0;
- do {
- k = (*s++ - '0') + 10*k;
- } while (++i < 5 && *s >= '0' && *s <= '9');
- if (i < 5) {
- for (i=0; i<dimof(qiclist); i++) {
- if (qiclist[i].nqic == k) {
- cmdset = qiclist[i].command; break;
- }
- }
- }
- }
- if (!cmdset) {
- errmsg = "invalid QIC number"; goto error;
- }
- } else {
- if (*s == ':') ++s;
- if (*s == '=') ++s;
- if (strncmp("base", lex, i) == 0) {
- for (id.base_address=0, i=0; i<5; ++i, s++) {
- register j = '0';
- if (*s>='A' && *s<='F') j = 'A' - 10;
- else if (*s>='a' && *s<='f') j = 'a' - 10;
- else if (*s <'0' || *s >'9') break;
- id.base_address = (id.base_address << 4) | (*s - j);
- }
- if (i<1 || i>4) {
- errmsg = "invalid base address"; goto error;
- }
- if (*s == 'h' || *s == 'H') ++s;
- } else if (strncmp("dma", lex, i) == 0) {
- if (*s<'0' || *s>'7') {
- errmsg = "invalid DMA channel number"; goto error;
- }
- id.dma_number = *s++ & 7;
- } else if (strncmp("irq", lex, i) == 0) {
- for (id.irq_number=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
- id.irq_number = 10*id.irq_number + *s - '0';
- }
- if (i<1 || i>2 || id.irq_number > 15) {
- errmsg = "invalid IRQ number"; goto error;
- }
- } else if (strncmp("tracks", lex, i) == 0) {
- if (cmdset) {
- errmsg = already; goto error;
- }
- for (k=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
- k = (*s - '0') + 10*k;
- }
- if (i > 0 && i < 3) {
- for (i=0; i<dimof(qiclist); i++) {
- if (qiclist[i].tracks == k) {
- cmdset = qiclist[i].command; break;
- }
- }
- }
- if (!cmdset) {
- errmsg = "invalid number of tracks"; goto error;
- }
- } else {
- (void)fprintf(stderr,"Tar: unknown parameter \'%s\'\n",lex);
- return ERROR;
- }
- }
- if (*s == '\0') break;
- if (*s != ',' && *s != ':' && *s != '.') {
- (void)fprintf(stderr,"Tar: invalid character after \'%s\'\n",lex);
- return ERROR;
- }
- }
- if (id.base_address == UNUSED) {
- errmsg = "base address must be specified"; goto error;
- }
- if (!cblock) cblock = 1;
- return TRUE;
- error:
- (void)fprintf(stderr,"Tar: %s\n", errmsg);
- return ERROR;
- }
-
- static void qerror(int k)
- {
- if (k < 0) {
- (void)fprintf(stderr, "Tar: %s\n", strerror(errno));
- } else if (k < qic02_nerr) {
- (void)fprintf(stderr, "Tar: %s\n", qic02_errlist[k]);
- } else {
- (void)fprintf(stderr, "Tar: error #%d\n", k);
- }
- }
-
- int qbegin(void)
- {
- register k;
-
- if (no_rewind) board_type |= SKIP_RESET;
- if ((k=streamer('o', &id, board_type)) != 0) {
- if (k != CTE_FAULT || errno != EINVDAT) goto error;
- (void)fprintf(stderr, "Tar: unsupported hardware configuration\n");
- return k;
- }
- if (setdrive) {
- if ((k=streamer('i',NULL,(1<<ndrive)&15/*|Q2_SELECT*/))!=0) goto error;
- }
- if (!no_rewind) {
- if ((k=c_flag ? streamer('i',NULL,Q2_ERASE) : streamer('n',NULL,0))!=0)
- goto error;
- if (cmdset) {/* select tape format */
- if ((k=streamer('i', NULL, cmdset)) != 0) goto error;
- }
- }
- return 0;
- error:
- qerror(k);
- return k;
- }
-
- void qend(void)
- {
- if (!no_rewind) streamer('n',NULL,0);
- streamer('c',NULL,0);
- }
-
- static void ioerror(unsigned mask)
- {
- register k;
- struct qic02_word_status s;
- extern int ct_errbit(unsigned);
-
- k = streamer('t', &s, 0);
- if (k >= 0 && k <= CTE_BUSY) {
- k = ct_errbit(mask & s.status);
- }
- qerror(k);
- }
-
- /* Interface routines */
- int qread(char *buf, register int n)
- {
- if (n & (BLKSIZE-1)) return -1;
- if (streamer('r', buf, n) != n) {
- ioerror(~(Q2E_BOM|Q2E_WRP));
- return -1;
- }
- return n;
- }
-
- int qwrite(char *buf, register int n)
- {
- n = (BLKSIZE-1 + n) & ~(BLKSIZE-1);
- if (streamer('w', buf, n) != n) {
- ioerror(~Q2E_BOM);
- return -1;
- }
- return n;
- }
-
- int qback(n)
- register n;
- {
- register j, k;
- for (j=(n+cblock-1)/cblock; j; j--)
- if ((k=streamer('i',NULL,Q2_REVERSE)) != 0) {
- qerror(k); return -1;
- }
- return n;
- }
- #endif
-
- char *getbuf(length)
- int length;
- {
- register char *ptr;
- #ifdef MSDOS
- int dw; /* size of DMA word */
-
- dw = id.dma_number & ~7 ? 0 : 1 + (id.dma_number >> 2);
- ptr = malloc(length);
- if (!ptr) {
- (void)fprintf(stderr, "Tar: not enough memory\n");
- } else if (dw > 0) {
- long a; register s;
-
- a = ptr2abs(ptr);
- s = dw + 15; /* shift factor to get DMA page number */
- /* Compare DMA pages */
- if ((a >> s) != ((a+length-1) >> s)) {
- /* Attempt to get DMA page-aligned buffer assumes: */
- /* - length is not greater than half of DMA page; */
- /* - malloc() heap is unfragmented. */
- register void *tmp;
-
- tmp = ptr; ptr = malloc(length); free(tmp);
- if (!ptr) {
- (void)fprintf(stderr, "Tar: no memory to align buffer\n");
- return (void *)0;
- }
- a = ptr2abs(ptr);
- if ((a >> s) != ((a+length-1) >> s)) {
- (void)fprintf(stderr, "Tar: fail to align buffer\n");
- free(ptr); return (void *)0;
- }
- }
- if (a & (dw - 1)) {
- (void)fprintf(stderr, "Tar: DMA buffer is not word-aligned\n");
- free(ptr); return (void *)0;
- }
- }
- return ptr;
- #else
- extern char *malloc();
- ptr = malloc(length);
- if (!ptr) (void)fprintf(stderr, "Tar: not enough memory\n");
- return ptr;
- #endif
- }